import type { NodeListItem } from '@/apis/model/node'
import {
  deleteApiNodeApi,
  postApiNodeControlApi,
  updateApiNodeApi
} from '@/apis/modules/node'
import {
  getApiNodeVersionCommandApi,
  getApiNodeVersionImprintApi,
  getApiNodeVersionQueryListApi,
  updateApiNodeVersionSwitchApi
} from '@/apis/modules/resolve/version'
import { NODE_OPERATIONS } from '@/constants'
import { Form, FormItem, Message, Select } from '@arco-design/web-vue'
import { useClipboard } from '@vueuse/core'
import type { JSX } from 'vue/jsx-runtime'
import IconArrowRight from '~icons/icons/arrow-right'
import IconCopy from '~icons/icons/copy'
export default function useCommand(reload: () => void) {
  const handleCommand = (
    command: string,
    ids: string[],
    row?: NodeListItem
  ) => {
    const {
      getVersionDescription,
      switchVersion,
      batchChangeVersion,
      singleVersionChange,
      getVersionOpts
    } = versionControl(reload)
    const controlNode = (type: NODE_OPERATIONS, content: string) => {
      const fn = () =>
        postApiNodeControlApi({ control_type: type, ids: ids }).then(() => {
          ToastUtils.success('操作成功')
          reload()
        })
      if ([NODE_OPERATIONS.STOP, NODE_OPERATIONS.RELOAD].includes(type)) {
        CloudModal.error(
          {
            maskClosable: false,
            content: content
          },
          fn
        )
      } else {
        CloudModal.confirm(
          {
            maskClosable: false,
            content: content
          },
          fn
        )
      }
    }
    const map: Record<string, () => void> = {
      start: () => {
        // 启用
        const content = `启用${ids.length > 1 ? '选中的' : ''}节点，开始向终端用户提供服务，确认继续？`
        controlNode(NODE_OPERATIONS.START, content)
      },
      stop: () => {
        const content = `停用${ids.length > 1 ? '选中的' : ''}节点，停止向终端用户提供服务，确认继续？`
        // 停用
        controlNode(NODE_OPERATIONS.STOP, content)
      },
      reload: () => {
        // 重启
        const content = `该操作会将${ids.length > 1 ? '选中' : '该'}节点的状态清空，并重新启动，确认继续？`
        controlNode(NODE_OPERATIONS.RELOAD, content)
      },
      join: () => {
        const fn = () =>
          updateApiNodeApi({ id: ids[0] as string, enable_resolve: true }).then(
            () => {
              ToastUtils.success('操作成功')
              reload()
            }
          )
        // 加入解析
        CloudModal.confirm(
          {
            maskClosable: false,
            content: '该操作将节点 IP 加入解析链路，确认继续？'
          },
          fn
        )
      },
      remove: () => {
        const fn = () =>
          updateApiNodeApi({
            id: ids[0] as string,
            enable_resolve: false
          }).then(() => {
            ToastUtils.success('操作成功')
            reload()
          })

        // 移除解析
        CloudModal.error(
          {
            maskClosable: false,
            content: '该操作将节点 IP 从解析链路中移除，确认继续？'
          },
          fn
        )
      },
      version: async () => {
        await getVersionOpts(true)
        let descriptions = ''
        if (ids.length === 1) {
          descriptions = await getVersionDescription(row!.version!)
        }
        const title = ids.length > 1 ? '批量切换版本' : '切换版本'
        const fn =
          ids.length > 1
            ? batchChangeVersion
            : singleVersionChange(descriptions, row?.version)

        CloudModal.normal(
          {
            title: title,
            maskClosable: false,
            width: ids.length > 1 ? 480 : 800,
            content: fn
          },
          () => switchVersion(ids)
        )
      },
      config: () => {
        // 批量同步配置
        const fn = () =>
          postApiNodeControlApi({
            control_type: NODE_OPERATIONS.SYNC,
            ids: ids
          }).then(() => {
            ToastUtils.success('操作成功')
            reload()
          })
        CloudModal.error(
          {
            maskClosable: false,
            content: () => (
              <div class="flex flex-col gap-y-6 text-1">
                <span>
                  该操作会重置所选节点的配置，清空并重新生成相关联站点配置，确认继续？
                </span>
                <span class="text-4">
                  *注意：若涉及到大量节点和站点时可能耗时较长
                </span>
              </div>
            )
          },
          fn
        )
      },
      cache: () => {
        // 清除缓存
        const fn = () =>
          postApiNodeControlApi({
            control_type: NODE_OPERATIONS.PURGE,
            ids: ids
          }).then(() => {
            ToastUtils.success('操作成功')
            reload()
          })
        CloudModal.error(
          {
            maskClosable: false,
            content:
              '该操作将永久清除所选节点的缓存，缓存将在数分钟后失效，确认继续？'
          },
          fn
        )
      },
      delete: () => {
        // 删除节点
        const fn = () =>
          deleteApiNodeApi({ id: ids[0] as string }).then(() => {
            ToastUtils.success('操作成功')
            reload()
          })
        CloudModal.error(
          {
            maskClosable: false,
            content: '该操作会删除并卸载节点，确认删除？',
            okText: '删除',
          },
          fn
        )
      },
      install_script: async () => {
        const { renderInstallScript, getScript, formState } = getInstallScript()
        await getScript(ids[0] as string)
        if (!formState.url) return false
        CloudModal.normal({
          title: '获取安装脚本',
          maskClosable: false,
          footer: false,
          content: renderInstallScript
        })
      }
    }
    map[command]()
  }
  return { handleCommand }
}

/**
 *
 * 安装脚本弹窗
 */
function getInstallScript() {
  const formState = reactive({ url: '' })
  const { copy } = useClipboard({ legacy: true })
  const handleCopy = (content: string) => {
    copy(content)
    Message.success('复制成功')
  }
  async function getScript(id: string) {
    return getApiNodeVersionCommandApi({
      id: id
    })
      .then((res) => {
        formState.url = res.command ?? ''
      })
      .catch(() => {
        return true
      })
  }
  const renderInstallScript = () => (
    <div class="flex flex-col gap-y-6 w-full text-1">
      <div class="flex justify-between">
        <span>请复制命令在目标节点目标服务器中进行安装</span>
        <span
          class="flex gap-x-6px items-center text-primary cursor-pointer"
          onClick={() => handleCopy(formState.url ?? '')}>
          <IconCopy />
          复制
        </span>
      </div>
      <div class="bg-#1D2129 rounded p-4 text-white">{formState.url}</div>
    </div>
  )

  return {
    formState,
    getScript,
    renderInstallScript
  }
}

/**
 * 版本切换弹窗
 * @param reload 重新获取列表数据
 * */
function versionControl(reload: () => void) {
  const versionsOpt = ref<LabelValue[]>([])

  const targetVersion = reactive({ version: '', id: '' })
  const targetDesc = ref('')
  // 版本说明
  function versionDescription(des?: string) {
    return (
      <FormItem label="版本说明" class="version-item">
        <div
          class={['text-4 text-wrap whitespace-pre-line', { 'text-2!': des }]}>
          {des && des !== '-' ? des : '此版本暂无说明'}
        </div>
      </FormItem>
      // <div class="flex flex-col gap-y-2">
      //   <span class="text-4">版本说明</span>
      //   <div
      //     class={['text-4 text-wrap whitespace-pre-line', { 'text-2!': des }]}>
      //     {des && des !== '-' ? des : '此版本暂无说明'}
      //   </div>
      // </div>
    )
  }

  function compareVersions(a: number[], b: number[], index: number): number {
    if (index > Math.max(a.length, b.length)) return 1
    if (a[index] > b[index]) return 1
    if (a[index] < b[index]) return -1
    return compareVersions(a, b, index + 1)
  }
  // 获取版本列表
  async function getVersionOpts(init: boolean = false) {
    try {
      const res = await getApiNodeVersionQueryListApi({ limit: 100 })
      const list = res.list ?? []
      versionsOpt.value =
        list.map((item) => ({
          label: item.version ?? '',
          value: item.id ?? ''
        })) ?? []
      if (init) {
        list.sort((a, b) => {
          const listA = a
            .version!.slice(1)
            .split('.')
            .map((item) => Number(item))
          const listB = b
            .version!.slice(1)
            .split('.')
            .map((item) => Number(item))

          return compareVersions(listB, listA, 0)
        })
        targetVersion.id = list[0].id ?? ''
        targetDesc.value = await getVersionDescription(list[0].version!)
      }
    } catch (_err) {
      console.error(_err)
      versionsOpt.value = []
    }
  }
  // 获取版本描述
  async function getVersionDescription(version: string): Promise<string> {
    try {
      if (!version) return ''
      const res = await getApiNodeVersionImprintApi({ version })
      return res.imprint ?? ''
    } catch (error) {
      console.error(error)
      return ''
    }
  }
  const versionChange = async (id: string) => {
    targetVersion.id = id
    const version =
      versionsOpt.value.find((item) => item.value === id)?.label ?? ''
    targetDesc.value = await getVersionDescription(version)
  }
  // 批量切换版本
  const batchChangeVersion = () => {
    return (
      <Form layout="vertical" model={targetVersion}>
        <FormItem
          asteriskPosition="end"
          label="切换版本"
          required
          field="id"
          hide-asterisk>
          <Select
            modelValue={targetVersion.id}
            options={versionsOpt.value}
            placeholder="请选择版本"
            onChange={(v) => versionChange(v as string)}></Select>
        </FormItem>
        {versionDescription(targetDesc.value)}
      </Form>
    )
  }

  function versionWrap(children: () => JSX.Element) {
    return (
      <div class="w-346px min-h-60 flex flex-col rounded gap-y-4 p-4 border border-dashed border-color-3 bg-fill-1">
        {children()}
      </div>
    )
  }
  // 单个版本切换
  const singleVersionChange = (desc: string, currentVersion: string = '') => {
    const currentInfo = () => (
      <Form model={{}} layout="vertical">
        <FormItem label="当前版本" class="version-item">
          <span class="text-2">{currentVersion || '-'}</span>
        </FormItem>
        {versionDescription(desc)}
      </Form>
    )
    return () => (
      <div class="flex gap-x-4 items-center h-full">
        {versionWrap(currentInfo)}
        <IconArrowRight />
        {versionWrap(batchChangeVersion)}
      </div>
    )
  }
  const switchVersion = (ids: string[]) =>
    updateApiNodeVersionSwitchApi({
      ids: ids,
      target_id: targetVersion.id
    }).then(() => {
      ToastUtils.success('操作成功')
      reload()
    })
  return {
    singleVersionChange,
    batchChangeVersion,
    switchVersion,
    getVersionDescription,
    getVersionOpts
  }
}
